#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<vector>
#define REP(i,n) for(int i=0;i<n;i++)
#define CLR(x,c) memset(x,c,sizeof x)
using namespace std;

void setIO(string name){
	string in=name+".in";
	string out=name+".out";
	freopen(in.c_str(),"r",stdin);
	freopen(out.c_str(),"w",stdout);
}

int n,nR,nC;
const int MAX_N=100000+10;

typedef long long int64;

int num=0;

struct Tree;
void reuse(Tree*a);

struct Tree{
	int l,r,h;//h is relative to it's father
	int64 sum;

	Tree*next,*first;

	Tree(int _l,int _r,int _h):l(_l),r(_r),h(_h){
		int64 w=r-l+1;
		sum=w*(w+1)/2*h;

		next=0;
		first=0;

		++num;
	}

	Tree(){

		++num;
	}


	Tree* set(int _l,int _r,int _h){
		l=_l;r=_r;h=_h;
		int64 w=r-l+1;
		sum=w*(w+1)/2*h;

		next=0;
		first=0;
		return this;
	}

	void recalcSum(){
		int64 w=r-l+1;
		sum=w*(w+1)/2*h;
		for(Tree*e=first;e;e=e->next)
			sum+=e->sum;
	}
	void addH(){
		++h;
		int64 w=r-l+1;
		sum+=w*(w+1)/2;
	}

	void addChild(Tree*c){
		c->next=first;
		first=c;
		sum+=c->sum;
	}

	void optimize(){
		if(first!=0){
			if(first->l==l&&first->r==r){
				reuse(first);
				h+=first->h;
				first=first->first;
			}
		}
	}
}*root;

const int MAX_R = 40000+10;

vector<int> byR[MAX_R];

int cnt;

const int BUFFER_SIZE=10000;

Tree*buffer=0,*cur=0;
Tree*stk[BUFFER_SIZE];
int top=0;

void reuse(Tree*a){
	//    return;
	if(top<BUFFER_SIZE)
		stk[top++]=a;
}

Tree*get(){
	if(top>0)
		return stk[--top];
	if(!buffer||cur==buffer+BUFFER_SIZE)
		buffer = new Tree[BUFFER_SIZE],cur=buffer;
	return cur++;
}

void splitTree(Tree*rt,int c,Tree*sp[2]){
	++cnt;

	Tree*chsp[2]={};

	Tree*prev=0;
	for(Tree*ch=rt->first;ch;ch=ch->next){
		if(ch->l<=c&&ch->r>=c){
			rt->sum-=ch->sum;
			if(prev)
				prev->next=ch->next;
			else {
				rt->first=ch->next;
			}
			splitTree(ch,c,chsp);
			REP(k,2)
				if(chsp[k]!=0)
					rt->addChild(chsp[k]);
			break;
		}
		prev=ch;
	}

	if(rt->h>0){
		//split rt
		if(rt->l<=c-1){
			sp[0]=get()->set(rt->l,c-1,rt->h);
		} else {
			sp[0]=0;
		}
		if(c+1<=rt->r){
			sp[1]=get()->set(c+1,rt->r,rt->h);
		} else {
			sp[1]=0;
		}

		//distrube the childs
		for(Tree*ch=rt->first,*nxt;ch;ch=nxt){
			nxt=ch->next;
			if(ch->r<=c-1){
				sp[0]->addChild(ch);
			} else{
				sp[1]->addChild(ch);
			}
		}

		REP(k,2)if(sp[k])
			sp[k]->optimize();
	} else {
		//needn't split rt
		//needn't do anything
	}
}

int64 ans;

void work(){
	root = get()->set(1,nC,0);

	ans=1LL*nR*(nR+1)/2*nC*(nC+1)/2;


	for(int r=1;r<=nR;++r){
		//split the tree
		vector<int>&cs=byR[r];
		//add a floor
		root->addH();

		REP(i,cs.size()){
			int c=cs[i];
			//put height c->0
			Tree*sp[2]={};
			cnt=0;
			if(root->h==0){
				splitTree(root,c,sp);
			} else {
				splitTree(root,c,sp);
				root = get()->set(1,nC,0);
				REP(k,2)if(sp[k])
					root->addChild(sp[k]);
				root->recalcSum();
			}
			//            cout<<cnt<<endl;
		}

		ans -= root->sum;
	}

	cout<<ans<<endl;
}

void readInput(){
	cin>>nR>>nC>>n;
	REP(i,n){
		int r,c;
		scanf("%d%d",&r,&c);
		byR[r].push_back(c);
	}
}

int main(){
	//setIO("mrx");
	readInput();
	work();
	return 0;
}

